package cn.t.facade.android;

import cn.t.constants.CommonConstants;
import cn.t.converter.order.OverPickupRecordDTOConverter;
import cn.t.converter.user.RoleSkuDTOConverter;
import cn.t.dto.device.CargowaySkuDTO;
import cn.t.dto.device.OpenCloseWeightVO;
import cn.t.dto.device.vo.QtyVO;
import cn.t.dto.device.vo.WeightVO;
import cn.t.dto.user.RoleSkuDTO;
import cn.t.dto.user.SkuQtyDTO;
import cn.t.enums.TimeLimitTypeEnum;
import cn.t.model.order.OrderDetailDO;
import cn.t.service.order.OrderDetailService;
import cn.t.utils.BusinessUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

/**
 * @author l
 */
@Slf4j
@Component
public class DeviceCommunicationFacade {
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private OverPickupRecordDTOConverter overPickupRecordDTOConverter;
    @Resource
    private RoleSkuDTOConverter roleSkuDTOConverter;
    @Resource
    private Executor executeIoExecutor;
    /**
     * 重力计算
     *
     * @param vo 前后重力数据(含商品单重、误差值)
     * @return 重力计算返回vo
     */
    public List<QtyVO> calcGravity(OpenCloseWeightVO vo) {
        List<QtyVO> list = Lists.newArrayList();
        if (null == vo) {
            return list;
        }
        // 货道商品单重信息
        Map<Integer, CargowaySkuDTO> cargowayMap = vo.getCargowayMap();
        // 开门重力数据
        Map<Integer, Double> open = vo.getOpenScale().stream().collect(Collectors.toMap(WeightVO::getNo, WeightVO::getWeight));
        // 关门重力数据
        Map<Integer, Double> close = vo.getCloseScale().stream().collect(Collectors.toMap(WeightVO::getNo, WeightVO::getWeight));
        for (Integer key : open.keySet()) {
            if (close.get(key) == null || open.get(key) == null) {
                log.error("重力数据为空 {}", key);
                QtyVO qtyVO = new QtyVO(key, null, null);
                list.add(qtyVO);
                continue;
            }
            // by货道重力计算
            BigDecimal diffWeight = BigDecimal.valueOf(close.get(key)).subtract(BigDecimal.valueOf(open.get(key)));
            Integer qty = null;
            if (!ObjectUtils.isEmpty(cargowayMap.get(key))) {
                qty = BusinessUtil.calcQty(
                        // 重力差 = 后 减去 前
                        diffWeight,
                        // 商品单重
                        cargowayMap.get(key).getSkuWeight(),
                        // 误差值 = 误差率*0.01*单重
                        new BigDecimal(cargowayMap.get(key).getErrorRate()).multiply(CommonConstants.POINT_ZERO_ONE).multiply(cargowayMap.get(key).getSkuWeight()),
                        // 称抖动误差 = 默认5g
                        CommonConstants.JITTER
                );
            } else {
                log.error("货道商品单重信息为空");
            }

            QtyVO qtyVO = new QtyVO(key, qty, diffWeight.doubleValue());
            list.add(qtyVO);
        }
        return list;
    }


    public List<SkuQtyDTO> getDayOverPickNumList(Long userId, Long firmId, List<RoleSkuDTO>  skuRoleList) {
        //过滤有限制的商品
        List<SkuQtyDTO> roleSkuDTOS = filterSkuRole(skuRoleList);
        Map<Date, List<SkuQtyDTO>> collect = roleSkuDTOS.stream().filter(roleSkuDTO -> Objects.nonNull(roleSkuDTO.getPickTimeStart())).collect(Collectors.groupingBy(SkuQtyDTO::getPickTimeStart));
        log.info("超领用权限时间分组 {}", JSON.toJSONString(roleSkuDTOS));
        CopyOnWriteArrayList<SkuQtyDTO> allQtyVO = new CopyOnWriteArrayList<>();
        // 等待所有异步任务完成
        CompletableFuture.allOf(collect.entrySet().stream()
                .map(entry -> {
                    Date timeStart = entry.getKey();
                    List<SkuQtyDTO> value = entry.getValue();
                    List<String> skuCodes = value.stream().map(SkuQtyDTO::getSkuCode).distinct().collect(Collectors.toList());

                    return CompletableFuture.supplyAsync(() -> orderDetailService.queryDetailByUserFirm(userId, firmId, skuCodes, timeStart).stream()
                            .collect(Collectors.groupingBy(OrderDetailDO::getSkuCode, Collectors.summingInt(OrderDetailDO::getQty)))).thenAccept(skuSumQtyMap -> {
                        value.forEach(roleSkuDTO -> roleSkuDTO.setPickQuantity(skuSumQtyMap.get(roleSkuDTO.getSkuCode()) == null ? 0 : skuSumQtyMap.get(roleSkuDTO.getSkuCode())));
                        allQtyVO.addAll(value);
                    });
                }).toArray(CompletableFuture[]::new)).join();
        return allQtyVO;
    }


    /**
     * //设置查询时间
     */
    public List<SkuQtyDTO> filterSkuRole( List<RoleSkuDTO> skuRoleList) {
        return roleSkuDTOConverter.dto2DTO(skuRoleList.stream().
                peek(roleSkuDTO -> {
                            TimeLimitTypeEnum anEnum = TimeLimitTypeEnum.getEnum(roleSkuDTO.getLimitedType());
                            if (anEnum == null || roleSkuDTO.getLimitedQuantity() == null) {
                                log.warn("超领用权限类型错误 {}", roleSkuDTO.getLimitedType());
                            } else {
                                Date timeLimit = overPickupRecordDTOConverter.getTimeLimit(anEnum, roleSkuDTO.getLimitedQuantity());
                                if (timeLimit != null) {
                                    roleSkuDTO.setPickTimeStart(timeLimit);
                                }


                            }
                        }
                ).collect(Collectors.toList()));
    }

}
